package org.restql.db.operation;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringBufferInputStream;
import java.io.StringReader;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import net.arnx.jsonic.JSON;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import org.json.JSONObject;
import org.restql.db.resource.DatabaseResource;
import org.restql.db.resource.RequestResource;
import org.restql.webapp.RestQLException;
import org.restql.webapp.ReturnType;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public abstract class DatabasePutPost extends DatabaseOperation {

	private static Log logger = LogFactory.getLog(DatabasePutPost.class);

	protected DatabasePutPost(DatabaseResource databaseResource, RequestResource requestResource) {
		super(databaseResource, requestResource);
	}

	public void executeSql(ServletInputStream inputStream, ReturnType retType) throws RestQLException {
		Map<String, String> fieldValueMap = null;
		/*
		if (retType == ReturnType.xml) {
			fieldValueMap = parseXmlRequest(inputStream, retType);
		} else if (retType == ReturnType.json) {
			fieldValueMap = parseJsonRequest(inputStream, retType);
		}
		*/
		fieldValueMap = parseServletRequest(retType);		
		try {
			doOperation(fieldValueMap);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RestQLException("Error executing SQL exception... fields correct?", e);
		}
	}
	
	private Map<String, String> parseServletRequest(ReturnType retType) {
		Map<String, String> fieldValueMap = new LinkedHashMap<String, String>();
		Map<String, String> params = (Map<String, String>)requestResource.getQueryParameters();
		for (String key : params.keySet()) {
			String tempKey = key.replaceAll("\\]","");
			String[] keyArr = tempKey.split("[");
			fieldValueMap.put(keyArr[1],params.get(key));
		}
		return fieldValueMap;
	}

	public Map<String, String> parseXmlRequest(InputStream inputStream, ReturnType retType)  throws RestQLException {
		Map<String, String> fieldValueMap = new LinkedHashMap<String, String>();
		try {
				DocumentBuilderFactory factory = DocumentBuilderFactory
						.newInstance();
				DocumentBuilder builder;
				builder = factory.newDocumentBuilder();
				Document postedXml = builder.parse(inputStream);
				Node node = postedXml.getFirstChild();
				//Node root = postedXml.getFirstChild();
				//if (! root.getNodeName().equals(this.requestResource.getDbName())) {
				//	logger.error("Root of supplied XML does not match resource.");
				//	throw new RestQLException("Improper root node: " + root.getNodeName(), null);
				//}
				//NodeList tables = root.getChildNodes();
				//for (int i = 0; i < tables.getLength(); i++) {
				//	if (tables.item(i).getNodeType() == Node.ELEMENT_NODE) {
				//		Node insertNode = tables.item(i);
				//		doOperation(insertNode);
				//	}
				//}
				NodeList fields = node.getChildNodes();
				for (int i = 0; i < fields.getLength(); i++) {
					if (fields.item(i).getNodeType() == Node.ELEMENT_NODE) {
						fieldValueMap.put(fields.item(i).getNodeName(), fields
								.item(i).getTextContent());
					}
				}
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			throw new RestQLException("Error parsing XML in PUT", e);
		} catch (SAXException e) {
			e.printStackTrace();
			throw new RestQLException("Error parsing XML in PUT", e);
		} catch (IOException e) {
			e.printStackTrace();
			throw new RestQLException("Error reading request", e);
		}
		return fieldValueMap;
	}

	public Map<String, String> parseJsonRequest(InputStream inputStream, ReturnType retType)  throws RestQLException {
		Map<String, String> fieldValueMap = new LinkedHashMap<String, String>();
		//fieldValueMap = (Map<String, String>) JSON.decode(inputStream, Map.class);
		try {
			StringBuffer sb = new StringBuffer();
			BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
			String line;
			while ((line = br.readLine()) != null) {
				sb.append(line).append("\n");
			}
			String requestDiagramString = sb.toString();
			
			JSONObject jo = new JSONObject(requestDiagramString);
			for (String key : (Set<String>) jo.keySet()) {
				fieldValueMap.put(key, jo.getString(key));
			}
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return fieldValueMap;
	}

	protected abstract void doOperation(Map<String, String> fieldValueMap) throws SQLException;

}
